package com.example.a_java.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.a_java.common.BusinessException;
import com.example.a_java.common.ResultCode;
import com.example.a_java.dto.AccountCreateDTO;
import com.example.a_java.dto.AccountTransactionDTO;
import com.example.a_java.entity.Account;
import com.example.a_java.entity.AccountTransaction;
import com.example.a_java.mapper.AccountMapper;
import com.example.a_java.mapper.AccountTransactionMapper;
import com.example.a_java.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 账户Service实现�?
 */
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService {

    @Autowired
    private AccountTransactionMapper accountTransactionMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Account createAccount(AccountCreateDTO accountCreateDTO) {
        // 创建账户
        Account account = new Account();
        account.setAccountNo(generateAccountNo());
        account.setAccountName(accountCreateDTO.getAccountName());
        account.setAccountType(accountCreateDTO.getAccountType());
        account.setCustId(accountCreateDTO.getCustId());
        account.setBalance(BigDecimal.ZERO);
        account.setFrozenAmount(BigDecimal.ZERO);
        account.setStatus(1); // 正常状�?
        account.setOpenTime(LocalDateTime.now());
        account.setBankName(accountCreateDTO.getBankName());
        account.setBankAddress(accountCreateDTO.getBankAddress());
        account.setRemark(accountCreateDTO.getRemark());
        account.setCreateTime(LocalDateTime.now());
        account.setUpdateTime(LocalDateTime.now());

        // 保存账户
        save(account);

        // 如果有初始存入金额，进行存款操作
        if (accountCreateDTO.getInitialAmount() != null && accountCreateDTO.getInitialAmount().compareTo(BigDecimal.ZERO) > 0) {
            AccountTransactionDTO transactionDTO = new AccountTransactionDTO();
            transactionDTO.setAccountId(account.getAccountId());
            transactionDTO.setAmount(accountCreateDTO.getInitialAmount());
            transactionDTO.setRemark("开户初始存款");
            deposit(transactionDTO);

            // 重新查询账户信息，包含更新后的余�?
            account = getById(account.getAccountId());
        }

        return account;
    }

    @Override
    public Page<Account> queryAccounts(Integer page, Integer size, String accountNo, String accountName,
                                      String bankName, Integer accountType, Integer status, 
                                      Long custId, String orderBy, String orderType) {
        Page<Account> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<Account> wrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        wrapper.like(StringUtils.hasText(accountNo), Account::getAccountNo, accountNo)
               .like(StringUtils.hasText(accountName), Account::getAccountName, accountName)
               .like(StringUtils.hasText(bankName), Account::getBankName, bankName)
               .eq(accountType != null, Account::getAccountType, accountType)
               .eq(status != null, Account::getStatus, status)
               .eq(custId != null, Account::getCustId, custId);
        
        // 添加排序
        if ("balance".equals(orderBy)) {
            if ("asc".equals(orderType)) {
                wrapper.orderByAsc(Account::getBalance);
            } else {
                wrapper.orderByDesc(Account::getBalance);
            }
        } else if ("openTime".equals(orderBy)) {
            if ("asc".equals(orderType)) {
                wrapper.orderByAsc(Account::getOpenTime);
            } else {
                wrapper.orderByDesc(Account::getOpenTime);
            }
        } else {
            // 默认按创建时间排�?
            if ("asc".equals(orderType)) {
                wrapper.orderByAsc(Account::getCreateTime);
            } else {
                wrapper.orderByDesc(Account::getCreateTime);
            }
        }
        
        return page(pageParam, wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Account deposit(AccountTransactionDTO accountTransactionDTO) {
        // 获取账户
        Account account = getById(accountTransactionDTO.getAccountId());
        if (account == null) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户不存在");
        }

        // 检查账户状?
        if (account.getStatus() == 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户已冻结");
        }

        // 存款金额必须大于0
        if (accountTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "存款金额必须大于0");
        }

        // 更新账户余额
        BigDecimal beforeBalance = account.getBalance();
        BigDecimal afterBalance = beforeBalance.add(accountTransactionDTO.getAmount());
        account.setBalance(afterBalance);
        account.setUpdateTime(LocalDateTime.now());
        updateById(account);

        // 记录交易流水
        saveTransaction(account, accountTransactionDTO.getAmount(), 1, 
                        beforeBalance, afterBalance, account.getFrozenAmount(), 
                        account.getFrozenAmount(), accountTransactionDTO.getRemark());

        return account;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Account withdraw(AccountTransactionDTO accountTransactionDTO) {
        // 获取账户
        Account account = getById(accountTransactionDTO.getAccountId());
        if (account == null) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户不存在");
        }

        // 检查账户状?
        if (account.getStatus() == 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户已冻结");
        }

        // 取款金额必须大于0
        if (accountTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "取款金额必须大于0");
        }

        // 检查可用余额是否足�?
        BigDecimal availableBalance = account.getBalance().subtract(account.getFrozenAmount());
        if (availableBalance.compareTo(accountTransactionDTO.getAmount()) < 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "可用余额不足");
        }

        // 更新账户余额
        BigDecimal beforeBalance = account.getBalance();
        BigDecimal afterBalance = beforeBalance.subtract(accountTransactionDTO.getAmount());
        account.setBalance(afterBalance);
        account.setUpdateTime(LocalDateTime.now());
        updateById(account);

        // 记录交易流水
        saveTransaction(account, accountTransactionDTO.getAmount(), 2, 
                        beforeBalance, afterBalance, account.getFrozenAmount(), 
                        account.getFrozenAmount(), accountTransactionDTO.getRemark());

        return account;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean freezeAccount(Long accountId, String remark) {
        // 获取账户
        Account account = getById(accountId);
        if (account == null) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户不存在");
        }

        // 检查账户状?
        if (account.getStatus() == 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户已冻结");
        }

        // 更新账户状?
        account.setStatus(0);
        account.setUpdateTime(LocalDateTime.now());
        updateById(account);

        // 记录交易流水（金额为0，只记录状态变更）
        saveTransaction(account, BigDecimal.ZERO, 3, 
                        account.getBalance(), account.getBalance(), account.getFrozenAmount(), 
                        account.getFrozenAmount(), "账户冻结" + (remark != null ? remark : ""));

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unfreezeAccount(Long accountId, String remark) {
        // 获取账户
        Account account = getById(accountId);
        if (account == null) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户不存在");
        }

        // 检查账户状?
        if (account.getStatus() == 1) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户未冻结");
        }

        // 更新账户状?
        account.setStatus(1);
        account.setUpdateTime(LocalDateTime.now());
        updateById(account);

        // 记录交易流水（金额为0，只记录状态变更）
        saveTransaction(account, BigDecimal.ZERO, 4, 
                        account.getBalance(), account.getBalance(), account.getFrozenAmount(), 
                        account.getFrozenAmount(), "账户解冻" + (remark != null ? remark : ""));

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Account freezeAmount(AccountTransactionDTO accountTransactionDTO) {
        // 获取账户
        Account account = getById(accountTransactionDTO.getAccountId());
        if (account == null) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户不存在");
        }

        // 检查账户状?
        if (account.getStatus() == 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户已冻结");
        }

        // 冻结金额必须大于0
        if (accountTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "冻结金额必须大于0");
        }

        // 检查可用余额是否足?
        BigDecimal availableBalance = account.getBalance().subtract(account.getFrozenAmount());
        if (availableBalance.compareTo(accountTransactionDTO.getAmount()) < 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "可用余额不足");
        }

        // 更新冻结金额
        BigDecimal beforeFrozen = account.getFrozenAmount();
        BigDecimal afterFrozen = beforeFrozen.add(accountTransactionDTO.getAmount());
        account.setFrozenAmount(afterFrozen);
        account.setUpdateTime(LocalDateTime.now());
        updateById(account);

        // 记录交易流水
        saveTransaction(account, accountTransactionDTO.getAmount(), 3, 
                        account.getBalance(), account.getBalance(), beforeFrozen, 
                        afterFrozen, accountTransactionDTO.getRemark());

        return account;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Account unfreezeAmount(AccountTransactionDTO accountTransactionDTO) {
        // 获取账户
        Account account = getById(accountTransactionDTO.getAccountId());
        if (account == null) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户不存在");
        }

        // 检查账户状?
        if (account.getStatus() == 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账户已冻结");
        }

        // 解冻金额必须大于0
        if (accountTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "解冻金额必须大于0");
        }

        // 检查冻结金额是否足?
        if (account.getFrozenAmount().compareTo(accountTransactionDTO.getAmount()) < 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "冻结金额不足");
        }

        // 更新冻结金额
        BigDecimal beforeFrozen = account.getFrozenAmount();
        BigDecimal afterFrozen = beforeFrozen.subtract(accountTransactionDTO.getAmount());
        account.setFrozenAmount(afterFrozen);
        account.setUpdateTime(LocalDateTime.now());
        updateById(account);

        // 记录交易流水
        saveTransaction(account, accountTransactionDTO.getAmount(), 4, 
                        account.getBalance(), account.getBalance(), beforeFrozen, 
                        afterFrozen, accountTransactionDTO.getRemark());

        return account;
    }

    /**
     * 生成账户�?
     *
     * @return 账户�?
     */
    private String generateAccountNo() {
        // 生成14位随机数作为账户号，以时间戳为基础
        return "AC" + System.currentTimeMillis() % 1000000000 + String.format("%04d", (int)(Math.random() * 10000));
    }

    /**
     * 保存交易流水
     *
     * @param account 账户
     * @param amount 交易金额
     * @param transactionType 交易类型
     * @param beforeBalance 交易前余�?
     * @param afterBalance 交易后余�?
     * @param beforeFrozen 交易前冻结金�?
     * @param afterFrozen 交易后冻结金�?
     * @param remark 备注
     */
    private void saveTransaction(Account account, BigDecimal amount, Integer transactionType, 
                                BigDecimal beforeBalance, BigDecimal afterBalance, 
                                BigDecimal beforeFrozen, BigDecimal afterFrozen, String remark) {
        AccountTransaction transaction = new AccountTransaction();
        transaction.setAccountId(account.getAccountId());
        transaction.setAccountNo(account.getAccountNo());
        transaction.setTransactionType(transactionType);
        transaction.setAmount(amount);
        transaction.setBeforeBalance(beforeBalance);
        transaction.setAfterBalance(afterBalance);
        transaction.setBeforeFrozen(beforeFrozen);
        transaction.setAfterFrozen(afterFrozen);
        transaction.setTransactionTime(LocalDateTime.now());
        transaction.setRemark(remark);
        transaction.setCreateTime(LocalDateTime.now());
        transaction.setUpdateTime(LocalDateTime.now());
        
        accountTransactionMapper.insert(transaction);
    }
} 
